#!/usr/bin/perl -w  
package clreqd_modules;

use strict;
use cldb;
use Config;

#########################################################################
# Improvement - the task to start the application is now run in the	#
# background here. If it takes longer than 5 secnods it returns a 	#
# OK PID=nnn - indicating the PID of the process which can then be 	#
# monitored by the start application script.				#
#									#
# This approach ensures that the request daemon is not tied up for	#
# long periods of time waiting for the application to start.		#
#########################################################################

sub stop_app {
my %ARGS=@_;
my $rc;

	local $SIG{CHLD}='DEFAULT';
	my $TIMEOUT;
	my $APP=$ARGS{APPLICATION};
	$TIMEOUT=$ARGS{TIMEOUT} if exists($ARGS{TIMEOUT});

	#################################################################
	# Get the details from the startscript and starttimeout		#
	#################################################################

	my $CLDB=new cldb("$::ENV{TRUECL_CFG}/config.db");
	if(!defined($CLDB)) {
		return "ERROR - Unable to config to 'config' database.";
	}
	my $res=$CLDB->get_rows("SELECT * FROM applications WHERE name = '$APP';");
	$CLDB->disconnect;
	if(!defined($res->[0]->{name})) {
		return "ERROR No such application found.";
	}
	if(!defined($TIMEOUT) && defined($res->[0]->{stoptimeout}) && $res->[0]->{stoptimeout} =~ /^\d+$/) {
		$TIMEOUT=$res->[0]->{stoptimeout};
	}
	$TIMEOUT=10 if ! defined($TIMEOUT);

	#################################################################
	# If no startscript is defined the simply return.		#
	#################################################################

	my $scr=$res->[0]->{stopscript};
	$scr="" if !defined($scr);
	$scr=~s/^\s+//;
	$scr=~s/\s+$//;
	if(!length($scr)) {
		return "OK 0";
	}

	my $pid=fork();
	my $running=1;
	if($pid) {
		local $!;
		if($TIMEOUT<=5) {
			my $ctime=time+$TIMEOUT;
			while(time<$ctime) {
				$rc=waitpid($pid,WNOHANG);
				if(!kill 0,$pid) {
					$running=0; last;
				}
				select(undef,undef,undef,.1);
			}
		} else {
			my $remaining=$TIMEOUT-5;
			my $ctime=time+5;
			#################################################
			# Wait for 5 seconds and treat normally, if	#
			# finish in this time period.			#
			#################################################
			while(time<$ctime) {
				$rc=waitpid($pid,WNOHANG);
				if(!kill 0,$pid) {
					$running=0; last;
				}
				select(undef,undef,undef,.1);
			}
			if($running) {
				return "OK PID=$pid";
			}
		}
	} else {
		# Write out the std-out to TRUECL_LOG/appstop-$APP.stdout
		# Write out the std-err to TRUECL_LOG/appstop-$APP.stderr
		open(STDOUT,">>$::ENV{TRUECL_LOG}/appstop-$APP.stdout");
		open(STDERR,">>$::ENV{TRUECL_LOG}/appstop-$APP.stderr");
		::msg("Running '$scr [See appstop-$APP.stdout/stderr]'.");
		my $wfd;
		my $dir="$::ENV{TRUECL_CODE}/monitors/mailbox";
		open($wfd,">$dir/.clreqd.$$");
		if(!defined($wfd)) {
			::warning("Error attempting to write to file '$dir/.clreqd.$$' : $!");
			exit(1);
		}
		$!=undef;
		system("$scr </dev/null");
		$rc=$?>>8;
		::msg("Completed script :: rc=$rc");
		if($rc) {
			::warning("Error running '$scr' : RC=$rc");
			print $wfd "1\n";
			close($wfd);
			exit(1);
		}
		print $wfd "$rc\n";
		close($wfd);
		exit($rc);
	};
	# Back to the parent  ... warning if still running.
	if($running) {
		return "WARNING Timeout in application shutdown.";
	}
	my $x=$?>>8;
	return "OK $x";
}

1;
